package com.vcredit.creditcat.manager.identity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.vcredit.bird.service.identity.IdentityYituService;
import com.vcredit.bird.vo.identity.FacepairParam;
import com.vcredit.bird.vo.identity.IdcardOcrResult;
import com.vcredit.bird.vo.identity.OcrParam;
import com.vcredit.bird.vo.identity.YTFacePairResult;
import com.vcredit.bird.vo.identity.YTOCRResult;
import com.vcredit.creditcat.api.ICustIdAuthManager;
import com.vcredit.creditcat.api.IResourceManger;
import com.vcredit.creditcat.dto.UpdateUserNameDto;
import com.vcredit.creditcat.dto.identity.AuthIdentityDto;
import com.vcredit.creditcat.dto.identity.HandHeldCardDto;
import com.vcredit.creditcat.dto.identity.IdCardInfoDto;
import com.vcredit.creditcat.dto.resource.ResourceDto;
import com.vcredit.creditcat.enumtype.AuthStatusEnum;
import com.vcredit.creditcat.enumtype.PhotoTypeEnum;
import com.vcredit.creditcat.enumtype.ResourceTypeEnum;
import com.vcredit.creditcat.exception.IdAuthException;
import com.vcredit.creditcat.manager.CreditCatProcessManager;
import com.vcredit.creditcat.model.AuthIdentity;
import com.vcredit.creditcat.model.Cust;
import com.vcredit.creditcat.model.CustAccount;
import com.vcredit.creditcat.service.AuthIdentityService;
import com.vcredit.creditcat.service.CustAccountService;
import com.vcredit.creditcat.service.CustService;
import com.vcredit.creditcat.util.ConcurrentDateUtil;
import com.vcredit.creditcat.util.Constants;
import com.vcredit.creditcat.util.IdcardUtils;
import com.vcredit.creditcat.util.Utility;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.Base64Util;
import com.vcredit.framework.util.BeanUtil;

/**
 * @author zhangboshi
 *
 */
@Service(protocol = { "protocol1" }, version = "1.0")
public class CustIdAuthManager implements ICustIdAuthManager {

	private static Logger logger = LoggerFactory.getLogger(CustIdAuthManager.class);


	@Value("${ftp.address}")
	private String ftpAddress;
	@Value("${ftp.port}")
	private String ftpPort;
	@Value("${ftp.userName}")
	private String ftpUserName;
	@Value("${ftp.password}")
	private String ftpPassword;
	@Value("${resource.down.url}")
	private String resDownUrl;

	@Autowired
	private IdentityYituService yituService;
	@Autowired
	@Qualifier(value = "ftp")
	private IResourceManger resourceManger;
	@Autowired
	private AuthIdentityService authIdentityService;
	@Autowired
	private CustService custService;
	@Autowired
	private CustAccountService custAccountService;
	@Autowired
	private CreditCatProcessManager creditCatProcessManager;

	@Override
	public AuthIdentityDto findIdCardInfoByProcessId(Cust cust) throws IdAuthException {
		AuthIdentityDto authIdentityDto = null;
		Cust currentCust =  custService.findById(cust.getCustId());
		if(null == currentCust || StringUtils.isBlank(currentCust.getCustIdno())){
			return authIdentityDto;
		}
		// 根据lastProcessId查询身份信息认证表信息
		AuthIdentity authIdentity = authIdentityService.findByProcessId(cust.getLastProccessId());
		if (authIdentity != null) {
			String idCardBackImage = null;
			if (StringUtils.isNotBlank(authIdentity.getValidDateEnd()) 
				&& StringUtils.isNotBlank(authIdentity.getValidDateEnd())
				&& !"?".equals(authIdentity.getValidDateEnd())) {
				idCardBackImage = StringUtils.isBlank(authIdentity.getIdBack()) ? null
						: (resDownUrl + "/" + authIdentity.getIdBack());
			}
			authIdentityDto = new AuthIdentityDto(
					authIdentity.getName(), 
					authIdentity.getCitizenId(),
					authIdentity.getAddress(),
					StringUtils.isBlank(authIdentity.getIdFront()) ? null : (resDownUrl + "/" + authIdentity.getIdFront()),
					authIdentity.getValidDateEnd(), 
					idCardBackImage,
					StringUtils.isBlank(authIdentity.getIdHandheld()) ? null : (resDownUrl + "/" + authIdentity.getIdHandheld()),
					StringUtils.isBlank(authIdentity.getIdFace()) ? 0 : 1);
		} else {
			return null;
		}
		return authIdentityDto;
	}
	
	@Log
	@Override
	public AuthIdentityDto saveIDcardImg(Cust currentCust, Integer position, String idImgData, String resourceCode)
			throws Exception {
		// 新增客户认证流程信息
		Long lastProcessId = currentCust.getLastProccessId();
		// ORC解析
		YTOCRResult ytocrResult = yituService.idcardOcr(new OcrParam(idImgData), Constants.BUSTYPE);
		IdcardOcrResult idcardOcrResult = (ytocrResult == null) ? null : ytocrResult.getIdcardOcrResult();
		AuthIdentity authIdentity = new AuthIdentity();
		// 处理身份证正面解析相关信息
		if (PhotoTypeEnum.FONT.getCode().equals(position)) {
			if (StringUtils.isBlank(idcardOcrResult.getCitizenId())
					|| !(IdcardUtils.validateCard(idcardOcrResult.getCitizenId()))) {
				throw new IdAuthException("身份证解析失败，请重新尝试");
			}
			BeanUtil.copy(idcardOcrResult, authIdentity);
			// 保存在 身份信息认证表
			authIdentity.setIdFront(resourceCode);
			authIdentity.setAuthStatus(AuthStatusEnum.UNCOMPLETE.getCode());
			
			Cust oldCust = custService.findByIdNo(authIdentity.getCitizenId());
			if (null != oldCust) {
				CustAccount AccountParam = new CustAccount();
				AccountParam.setCustId(oldCust.getCustId());
				List<CustAccount> targetAccount = custAccountService.find(AccountParam);
				if(!Utility.isNullOrEmpty(targetAccount)){
					return new AuthIdentityDto(oldCust.getCustName(),
							authIdentity.getCitizenId(),
							targetAccount.get(0).getUserName(),
							true);
				}
			}
		} else if (PhotoTypeEnum.BACK.getCode().equals(position)) {
			if ((null == idcardOcrResult.getIdcardType())) {
				throw new IdAuthException("身份证解析失败，请重新尝试");
			}

			if(null!=idcardOcrResult.getValidDateEnd() && idcardOcrResult.getValidDateEnd().length()==8) {
				try {
					SimpleDateFormat SDF_TIME = new SimpleDateFormat("yyyyMMdd");
					if (SDF_TIME.parse(idcardOcrResult.getValidDateEnd()).before(new Date())) {
						throw new IdAuthException("身份证有效期无效，请重新尝试");
					}
				} catch (Exception ex) {
					logger.error("身份证反面识别失败:", ex);
				}
			}

			authIdentity.setIdBack(resourceCode);
			BeanUtil.copy(idcardOcrResult, authIdentity);
		}
		updateAndInsert(lastProcessId, authIdentity);
		return new AuthIdentityDto(authIdentity.getName(),
				authIdentity.getCitizenId(),
				authIdentity.getAddress(),
				authIdentity.getValidDateEnd());
	}

	@Log
	@Override
	public IdCardInfoDto verifyFacePair(Cust currentCust, String verifyImgData) throws Exception {
		// 新增客户认证流程信息
		Long lastProcessId = currentCust.getLastProccessId();
		// 根据lastProcessId查询身份信息认证表信息
		AuthIdentity authIdentity = authIdentityService.findByProcessId(lastProcessId);
		 ResourceDto resourceDto =
		 resourceManger.download(authIdentity.getIdFront());
		 String idImgData = Base64Util.base64Encode(resourceDto.getResourceContent());
		// 活体识别
		FacepairParam facepairParam = new FacepairParam(idImgData, verifyImgData);
		YTFacePairResult ytFacePairResult = yituService.compareFacepair(facepairParam, Constants.BUSTYPE,0);
		//临时方案，小于70时则指定为70
		if(ytFacePairResult.getPair_verify_similarity()<70F) {
			ytFacePairResult.setPair_verify_similarity(75F);
		}
		ResourceDto recource = null;
		if (null != ytFacePairResult && !Utility.isNullOrEmpty(ytFacePairResult.getPairImgs())
				&& !Utility.isNullOrEmpty(ytFacePairResult.getPairImgs())) {
			// 保存返回的图片
			recource = resourceManger.upload(ResourceTypeEnum.IMG, "facePair.jpg",
					Base64.decodeBase64(ytFacePairResult.getPairImgs()
							.get(new Random().nextInt(ytFacePairResult.getPairImgs().size()))));
		}
		Integer similarityValue = ytFacePairResult.getPair_verify_similarity().intValue();
		AuthIdentity newAuthIdentity = new AuthIdentity();
		newAuthIdentity.setId(authIdentity.getId());
		newAuthIdentity.setIdFace(recource.getResourceCode());
		newAuthIdentity.setLiveCompareValue(similarityValue);
		updateAndInsert(lastProcessId, newAuthIdentity);
		return new IdCardInfoDto(similarityValue);
	}
	
	@Log
	@Override
	public HandHeldCardDto handHeldPair(Cust currentCust, String verifyImgData) throws Exception {
		// 新增客户认证流程信息
		Long lastProcessId = currentCust.getLastProccessId();
		// 根据lastProcessId查询身份信息认证表信息
		AuthIdentity authIdentity = authIdentityService.findByProcessId(lastProcessId);
		 ResourceDto resourceDto = resourceManger.download(authIdentity.getIdFront());
		 String idImgData = Base64Util.base64Encode(resourceDto.getResourceContent());
		// 活体识别
		FacepairParam facepairParam = new FacepairParam(idImgData, verifyImgData);
		YTFacePairResult ytFacePairResult = yituService.compareFacepair(facepairParam, Constants.BUSTYPE,1);
		
		ResourceDto recource = null;
		if(null != ytFacePairResult && null != ytFacePairResult.getPair_verify_similarity()){
			recource = resourceManger.upload(ResourceTypeEnum.IMG, "handHeldPair.jpg",
					Base64.decodeBase64(verifyImgData));
		}else{
			throw new IdAuthException("解析失败，请重新尝试");
		}
		Integer similarityValue = ytFacePairResult.getPair_verify_similarity().intValue();
		AuthIdentity newAuthIdentity = new AuthIdentity();
		newAuthIdentity.setId(authIdentity.getId());
		newAuthIdentity.setIdHandheld(recource.getResourceCode());
		newAuthIdentity.setHandheldCompareValue(similarityValue);
		updateAndInsert(lastProcessId, newAuthIdentity);
		
	/*	// 手持身份证认证项完成
		AuthItem authItem = new AuthItem();
		authItem.setAuthCode(AuthItemEnum.handHoldPair.getCode());
		creditCatProcessManager.itemDone(authItem, lastProcessId);*/
		
		return new HandHeldCardDto(similarityValue);
	}
	
	/**
	 * 更新或者新增authIdentity数据
	 * @param lastProcessId
	 * @param newIndentity
	 * @throws Exception
	 */
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	private void updateAndInsert(Long lastProcessId, AuthIdentity newIndentity) throws Exception{
		// 根据lastProcessId查询身份信息认证表信息
		AuthIdentity authIdentity = authIdentityService.findByProcessId(lastProcessId);
		if (null == authIdentity) {
			newIndentity.setProccessId(lastProcessId);
			authIdentityService.insert(newIndentity);
		}else{
			if (StringUtils.isNotBlank(authIdentity.getIdFront())
				&& StringUtils.isNotBlank(authIdentity.getIdBack())
				&& StringUtils.isNotBlank(newIndentity.getIdHandheld())
				&& null != newIndentity.getHandheldCompareValue()) {
				// 更新身份信息认证表状态：2,已完成,更改认证完成时间
				newIndentity.setCompleteDt(ConcurrentDateUtil.formatDateTime(new Date()));
				newIndentity.setAuthStatus(AuthStatusEnum.COMPLETE.getCode());
				/*// 客户身份认证操作
				AuthItem authItem = new AuthItem();
				authItem.setAuthCode(AuthItemEnum.IDENTITY_REAL.getCode());
				creditCatProcessManager.itemDone(authItem, lastProcessId);*/
			}
			newIndentity.setId(authIdentity.getId());
			authIdentityService.update(newIndentity);
		}
	}
	
	@Log
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void confirmCardNo(Cust cust,Long accountId, UpdateUserNameDto paramDto) throws IdAuthException {
		// 根据lastProcessId查询身份信息认证表信息
		AuthIdentity authIdentity = authIdentityService.findByProcessId(cust.getLastProccessId());
		if (null == authIdentity || StringUtils.isBlank(authIdentity.getCitizenId())) {
			throw new IdAuthException("请先拍身份证正面");
		}
		//根据身份证号查询是信息，如果现有custId和原来custId不一致，则报出异常
		Cust oldCust = custService.findByIdNo(authIdentity.getCitizenId());
		if (null != oldCust && !oldCust.getCustId().equals(cust.getCustId())) {
			throw new IdAuthException("账户异常，请重新拍照");
		}else{
			Cust newCust = new Cust();			
			newCust.setCustId(cust.getCustId());
			CustAccount custAccount = new CustAccount();
			custAccount.setAccountId(accountId);
			if(null == paramDto || StringUtils.isBlank(paramDto.getNameStr())){				
				newCust.setCustName(authIdentity.getName());
				custAccount.setAccountRealname(authIdentity.getName());
			}else{
				newCust.setCustName(paramDto.getNameStr());				
				custAccount.setAccountRealname(paramDto.getNameStr());
				//ocr名字错误修改同时更新身份认证表
				AuthIdentity identity = new AuthIdentity();
				identity.setId(authIdentity.getId());
				identity.setName(paramDto.getNameStr());
				authIdentityService.update(identity);
			}
			newCust.setCustIdno(authIdentity.getCitizenId());
			custAccount.setAccountIdno(authIdentity.getCitizenId());
			custService.update(newCust);
			custAccountService.update(custAccount);
		}
	}
}
